/**
 * 摇杆事件
 *
 * 这里只管事件，不处理摇杆的ui
 * */

//先阻止微信浏览器下拉
// document.body.addEventListener('touchmove' , function(e){
//     e.preventDefault();
// },true);

const pi = Math.PI

type OnJoystickChangeFnT = (
  angel: number,
  distance: number,
  x: number,
  y: number
) => void

/**
 * 摇杆
 * */
export default class JoystickEvent {
  private enabled = true

  private readonly stage: egret.Stage
  private readonly stickRadius: number

  private onJoystickChangeFn: OnJoystickChangeFnT

  private startP?: [number, number, number] //[id,x,y] 本次移动的开始位置，会把摇杆挪到此位置。id是点的id，只有这个点移动，才是本摇杆的
  private hasEvent = false

  /**
   * @param stage
   * @param stickRadius 摇杆活动范围的直径，单位px。
   * 用于计算用户操作摇杆偏移的距离与该值的百分比（从0到1）超过的100%的认为是100%。
   * 如果该值为0，则返回具体的距离，此时单位是px
   * */
  constructor(stage: egret.Stage, stickRadius: number = 0) {
    this.stage = stage
    this.stickRadius = stickRadius
  }

  /**
   * @param fn(angel,distance)
   * @param fn.angel 摇杆当前的方向，弧度角，正上是0，正右是PI/2，正下是PI，正左是3*PI/2
   * @param fn.distance 摇杆与中心点距离，范围从0到1。保留两位小数。
   * ps. 距离为0时，理论上是没有角度的，但是这里会返回速度为0前最后的角度
   * */
  public onJoystickChange(fn: OnJoystickChangeFnT) {
    this.onJoystickChangeFn = fn
    if (!this.hasEvent) {
      this.stage.addEventListener(
        egret.TouchEvent.TOUCH_BEGIN,
        this.touchstart,
        this
      )
      this.stage.addEventListener(
        egret.TouchEvent.TOUCH_MOVE,
        this.touchmove,
        this
      )
      this.stage.addEventListener(
        egret.TouchEvent.TOUCH_END,
        this.touchend,
        this
      )

      this.hasEvent = true
    }
  }

  private touchstart(e: egret.TouchEvent) {
    if (!this.enabled || this.startP) return
    this.startP = [0, e.stageX, e.stageY]
  }

  private touchmove(e: egret.TouchEvent, isEnd = false) {
    // e.preventDefault();
    // e.stopPropagation();
    if (!this.enabled || !this.startP) return

    const p: number[] = [0, e.stageX, e.stageY]

    if (isEnd) {
      this.startP = undefined
      this.onJoystickChangeFn(0, 0, 0, 0)
      return
    }
    let x = p[1] - this.startP[1]
    let y = p[2] - this.startP[2]
    const thirdLength = Math.abs(
      (x === 0 && y) ||
        (y === 0 && x) ||
        Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
    ) //斜边长度

    let angle = 0
    if (!((x === 0 && y === 0) || (x === 0 && y < 0))) {
      if (x === 0 && y > 0) angle = pi
      else if (y === 0 && x > 0) angle = pi / 2
      else if (y === 0 && x < 0) angle = pi * 1.5
      else {
        angle = Math.atan(Math.abs(x / y))
        if (x > 0 && y > 0) {
          angle = pi - angle
        } else if (x < 0 && y > 0) {
          angle += pi
        } else if (angle && x < 0 && y < 0) {
          angle = pi * 2 - angle
        }
      }
    }

    if (this.stickRadius) {
      const lengthScale = this.stickRadius / thirdLength
      // 要确认终点是不是在摇杆圈内
      if (lengthScale < 1) {
        x *= lengthScale
        y *= lengthScale
      }
    }

    this.onJoystickChangeFn(
      angle,
      this.stickRadius
        ? Math.round(Math.min(1, thirdLength / this.stickRadius) * 100) / 100
        : thirdLength,
      x,
      y
    )
  }

  private touchend(e) {
    return this.touchmove(e, true)
  }
}
